---
title: "Theming: Customising the grid with CSS"
---

Customising the grid with CSS

While the grid provides [parameters](./theming-parameters/) and [parts](./theming-parts/) for the most common customisations, it's not practical to provide a parameter for every possible customisation. Most grid applications, especially those with precise design requirements, use CSS to fine-tune the look of the grid.

## Custom CSS Rules

A running grid instance contains thousands of DOM elements, and each of them has class names like `ag-header` and `ag-row`. You can target these class names with your own CSS rules, allowing limitless customisation.

If your designer has specified, for example, animated rainbow text on the header, that's achievable:

```css
.ag-header-cell-text {
    background: linear-gradient(90deg, red, orange, yellow, green, blue, indigo, violet, red);
    font-weight: 600;
    font-size: 20px;
    animation: animatedTextGradient 2.5s linear infinite;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    background-size: 200% auto;
}

@keyframes animatedTextGradient {
    to {
        background-position: -200% center;
    }
}
```

{% gridExampleRunner title="CSS Rules" name="css-rules"  exampleHeight=450 /%}

The best way to find the right class name to use in a CSS rule is using the browser's developer tools. You will notice that components often have multiple class names, some more general than others. For example, the Column Drop component is an area into which you can drag columns. There are two kinds - a horizontal one in the [row group panel](./grouping-group-panel/) and a vertical one in the [columns tool panel](./tool-panel-columns/#example). You can use the class name `ag-column-drop` to target either kind, or `ag-column-drop-vertical` / `ag-column-drop-horizontal` to target one only.

## Overriding Theme Parameters with Custom Properties

Themes created by the Theming API support over a hundred [Theme Parameters](./theming-parameters/#finding-theme-parameters). The values provided through the Theming API are default values, and can be overridden using CSS, meaning that many grids can share the same theme and CSS can be used to create differences between the grids.

The names of the CSS custom properties are prefixed with `--ag-` to avoid conflicts with other custom properties in your application, and use kebab-case:

```css
body {
    /* override value of backgroundColor, foregroundColor and spacing parameters */
    --ag-background-color: darkred;
    --ag-foreground-color: lightpink;
    --ag-spacing: 4px;
    /* use dark scrollbars */
    --ag-browser-color-scheme: dark;
}
```

{% gridExampleRunner title="Custom Properties" name="custom-properties"  exampleHeight=450 /%}

Values for CSS custom properties are inherited by child elements. The above example sets the custom property on the `body` element, so will affect every grid on the page. You can use different selectors to target individual grids or groups of grids.

### Using Your App's Existing Custom Properties

If your app already defines a colour scheme using CSS custom properties and you want to use those values within the grid, you can use `var()` expressions as parameter values:

```css
body {
    /* use --appMainTextColor as the foreground color for all grids on the page */
    --ag-foreground-color: var(--appMainTextColor);
}
```

### Understanding CSS rule maintenance and breaking changes

With each release of the grid we add features and improve existing ones, and as a result the DOM structure changes with every release - even minor releases. Of course we test and update the CSS rules in our themes to make sure they still work, and this includes ensuring that customisations made via CSS custom properties do not break between releases. But if you have written your own CSS rules, you will need to test and update them.

The simpler your CSS rules are, the less likely they are to break between releases. Prefer selectors that target a single class name where possible.

### Avoiding Breaking the Grid with CSS Rules

Browsers use the same mechanism - CSS - for controlling how elements work (e.g. scrolling and whether they respond to mouse events), where elements appear, and how elements look. Some of the styles applied by our CSS are essential to how the grid works, and the grid depends on those rules not being overridden. There is nothing that we can do to prevent themes overriding critical rules, so as a theme author you need to be careful not to break the grid. Here's a guide:

* Visual styles including margins, paddings, sizes, colours, fonts, borders etc are all fine to change in a theme.

* Setting a component to `display: flex` and changing flex child layout properties like `align-items`, `align-self` and `flex-direction` is probably OK if you're trying to change how something looks on a small scale, e.g. to change the alignment of some text or icons within a container; but if you're trying to change the layout of the grid on a larger scale e.g. turning a vertical scrolling list into a horizontal one, you are likely to break Grid features.

* The style properties `position`, `overflow` and `pointer-events` are intrinsic to how the grid works. Changing these values will change how the grid operates, and may break functionality now or in future minor releases.

## CSS Layers

[Layers](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) are a CSS feature that allow you to split your CSS into ordered layers so that rules in later layers always override rules in earlier layers, even if the selectors in earlier layers are more [specific](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity).

By default the grid loads its styles without a layer, meaning that they will override all styles defined in a layer. If your application loads its styles into a CSS layer, you can load the grid styles into an earlier layer so that application styles can override grid styles.

To set the layer that the grid styles are loaded into, use the `themeCssLayer` grid option. You may want to use [global grid options](./grid-interface/#global-grid-options) to set this on all grids in your app.

{% note %}
By default, grid styles are inserted at the start of the document head, making the grid layer the first in the document and causing _all_ other styles to override grid styles. If you are setting `themeCssLayer`, you probably also want to move the grid styles later in the document by setting `themeStyleContainer` to the document body. This will ensure that your application styles come before the grid styles, and allow them to declare an order to css layers using e.g. `@layer resets, grid, application;`.
{% /note %}

In the following example the header is colored red using styles in the `application` layer, which comes after the `grid` layer allowing it to override the default header colour:

{% gridExampleRunner title="CSS Layers" name="css-layers"  exampleHeight=450 /%}